
namespace Nadine
{


	//====================================================================================
	class NDCHCSP :public NDBaseObject
	{
	private:

		//----- KD TREE -----
		bool 									m_bRenderBoundingVolume;
		NDCHCSPNode*							m_myNode;
		

		//----- CHC -----
		NDCHCSPQueryHandler*					m_pMyQueryHandler;
		NDCHCSPQueryQueue						m_QueryQueue;
		NDCHCSPTraversalQueue 					m_myDistanceQueue;

		bool									m_bUseMultiQueries;
		std::queue< sCHCSPNode* >				m_VQueue;
		std::vector< sCHCSPNode* >				m_IQueue;

		UINT									m_nMaxBatchSize;

		int 				 					m_nFrameID;
		int										m_nAssumedVisibleFrames;
		int 									m_nVisibilityThreshold;		// visible pixel threshold

		bool 									m_bIsQueryMode;				// render state

		bool									m_bUseOptimization;

		//MULTITHREAD FINALIZE CHCSP
		bool									m_bUsingMT;
		NDUID									m_nFinalizeCHCWorkID;
		bool									m_bKDTreeInited;


		//----- statistics -----
		sCHCTraversalStatistics					m_sTS;

	protected:

		//----- render traverser -----
		void 	RenderCullFrustum( float fElapsedTime );								//! renders the scene with view frustum culling only
		void 	RenderStopAndWait( float fElapsedTime );								//! renders the scene with the hierarchical stop and wait algorithm
		void 	RenderCoherentWithQueue( float fElapsedTime );							//! renders the scene with the coherent hierarchical algorithm and the query queye
		void	RenderAdvancedCoherentWithQueue( float fElapsedTime );

		void 	Preprocess(int nRenderMode);											//! does some importand initialisations
		
		void 	TraverseNode(sCHCSPNode *node, float fElapsedTime);						//! the node is traversed as usual
		void 	PullUpVisibility(sCHCSPNode *node);										//! visibility is pulled up from visibility of children 
		
		NDCHCSPOcclusionQuery* GetNextMultiQuery(std::vector<sCHCSPNode*>& iqueue);
		NDCHCSPOcclusionQuery* IssueOcclusionQuery(sCHCSPNode *node);
		void 	IssueOcclusionQuery(const NDCHCSPOcclusionQuery &query);				/** Issue multiquery.*/
		void	IssueMultiQueries();
		
		void	HandleACWQResult( NDCHCSPOcclusionQuery* pQ, float fElapsedTime );
		
		void 	Switch2GLRenderState();													//! switches to normal render mode
		void 	Switch2GLQueryState();													//! switches to occlusion query mode (geometry not rendered on the screen)		
		


	public:
		explicit NDCHCSP(NDArk* pArk);
		virtual ~NDCHCSP()
		{
			assert( m_myNode ==0 );

			assert( m_QueryQueue.size() ==0 );
			assert( m_myDistanceQueue.size() ==0 );

			assert( m_pMyQueryHandler ==0 );
		}

		//common func.
		virtual void release();

		//! adds geometry to this node (rendered if this node is a leaf)
		//void 	AddGeometry( NDCHCSPGeometry* pGeometry ) { this->AddGeometryIntoNode( this->m_myRootNode, pGeometry ); }
		void 	AddGeometry( NDCHCSPGeometry* pGeometry );

		/**
			initialises the k-d tree and the static termination criteria.
			this method must be called after all geometry has been added to the root node
			and before the tree has been generated.
		*/
		void 	InitKdTree()
		{
			assert( this->m_bKDTreeInited ==false );
			this->m_myNode->InitKdTree();
			this->m_bKDTreeInited =true;
		}

		void	InitKdTree_MT();
		bool	isKdTreeInited();
		
		int 	getNumHierarchyNodes();									//! returns number of nodes in hierarchy with this node.
		int 	getVisibilityThreshold();								//! returns visibility threshold

		int  	getNumTraversedNodes();									//! returns number of traversed nodes
		int 	getNumQueryCulledNodes();								//! returns the number of hierarchy nodes culled by the occlusion query
		int 	getNumFrustumCulledNodes();								//! returns the number of hierarchy nodes culled by the frustum culling only
		int 	getNumRenderedGeometry();								//! returns number of rendered geometric objects (e.g., teapots, ...)

		void 	setRenderBoundingVolume(bool renderBoundingVolume);		//! visibly renders also bounding volume of this node
		void 	setViewpoint(NDVECTOR3 const &viewpoint);				//! sets viewpoint
		void	setFrustumEq(NDVECTOR4* pFrustumEq); 					//! NDVECTOR4[6]
		void 	setVisibilityThreshold(int threshold);					//! sets visible pixels threshold for visibility classification
		void 	setUseOptimization(bool useOptimization);				//! use optimization to take leaf nodes instead of bounding box for occlusion queries	

		void	render( float fElapsedTime, eNDCHCSPRM renderMode =RENDER_COHERENT );
		void	renderVisualization( float fElapsedTime );


		


	};

	//====================================================================================
	class NDCHCSP_FinilizeCHCSP_MT :public NDW32WorkThread
	{
	private:
		NDCHCSP* m_myCHCSP;

	protected:
	public:
		explicit NDCHCSP_FinilizeCHCSP_MT( NDArk* pArk, NDCHCSP* pCHCSP ) :NDW32WorkThread( pArk, NDNORMALWORKTHREADID  ), m_myCHCSP( pCHCSP ) {}
		virtual ~NDCHCSP_FinilizeCHCSP_MT() {}

		virtual void threadExecute( UINT nThreadNo );
		virtual void release();

	};




}


